Index: crypto/openssl/crypto/bn/bn_print.c
===================================================================
--- crypto/openssl/crypto/bn/bn_print.c	(revision 284286)
+++ crypto/openssl/crypto/bn/bn_print.c	(working copy)
@@ -71,6 +71,12 @@ char *BN_bn2hex(const BIGNUM *a)
 	char *buf;
 	char *p;
 
+	if (a->neg && BN_is_zero(a)) {
+	    /* "-0" == 3 bytes including NULL terminator */
+	    buf = OPENSSL_malloc(3);
+	} else {
+	    buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
+	}
 	buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2);
 	if (buf == NULL)
 		{
Index: crypto/openssl/crypto/cms/cms_smime.c
===================================================================
--- crypto/openssl/crypto/cms/cms_smime.c	(revision 284286)
+++ crypto/openssl/crypto/cms/cms_smime.c	(working copy)
@@ -141,7 +141,7 @@ static void do_free_upto(BIO *f, BIO *upto)
 			BIO_free(f);
 			f = tbio;
 			}
-		while (f != upto);
+		while (f && f != upto);
 		}
 	else
 		BIO_free_all(f);
Index: crypto/openssl/crypto/ec/ec2_smpl.c
===================================================================
--- crypto/openssl/crypto/ec/ec2_smpl.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ec2_smpl.c	(working copy)
@@ -657,7 +657,8 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group
 		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
Index: crypto/openssl/crypto/ec/ec_check.c
===================================================================
--- crypto/openssl/crypto/ec/ec_check.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ec_check.c	(working copy)
@@ -88,7 +88,7 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR);
 		goto err;
 		}
-	if (!EC_POINT_is_on_curve(group, group->generator, ctx))
+	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
Index: crypto/openssl/crypto/ec/ec_key.c
===================================================================
--- crypto/openssl/crypto/ec/ec_key.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ec_key.c	(working copy)
@@ -316,7 +316,7 @@ int EC_KEY_check_key(const EC_KEY *eckey)
 		goto err;
 
 	/* testing whether the pub_key is on the elliptic curve */
-	if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx))
+	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
Index: crypto/openssl/crypto/ec/ec_lib.c
===================================================================
--- crypto/openssl/crypto/ec/ec_lib.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ec_lib.c	(working copy)
@@ -1040,7 +1040,15 @@ int EC_POINT_is_at_infinity(const EC_GROUP *group,
 	}
 
 
-int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
+/*
+ * Check whether an EC_POINT is on the curve or not. Note that the return
+ * value for this function should NOT be treated as a boolean. Return values:
+ *  1: The point is on the curve
+ *  0: The point is not on the curve
+ * -1: An error occurred
+ */
+int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+                         BN_CTX *ctx)
 	{
 	if (group->meth->is_on_curve == 0)
 		{
Index: crypto/openssl/crypto/ec/ecp_smpl.c
===================================================================
--- crypto/openssl/crypto/ec/ecp_smpl.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ecp_smpl.c	(working copy)
@@ -983,7 +983,8 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group,
 		if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
 		}
 	
-	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
+	/* test required by X9.62 */
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0)
 		{
 		ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
 		goto err;
Index: crypto/openssl/crypto/ec/ectest.c
===================================================================
--- crypto/openssl/crypto/ec/ectest.c	(revision 284286)
+++ crypto/openssl/crypto/ec/ectest.c	(working copy)
@@ -267,7 +267,7 @@ void prime_field_tests()
 
 	if (!BN_hex2bn(&x, "D")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 		if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT;
 		fprintf(stderr, "Point is not on curve: x = 0x");
@@ -363,7 +363,7 @@ void prime_field_tests()
 	if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT;
 	if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
@@ -407,7 +407,7 @@ void prime_field_tests()
 
 	if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
@@ -453,7 +453,7 @@ void prime_field_tests()
 
 	if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
 
@@ -499,7 +499,7 @@ void prime_field_tests()
 
 	if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E"
 		"84F3B9CAC2FC632551")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
@@ -550,7 +550,7 @@ void prime_field_tests()
 	if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B"
 		"9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT;
 	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
@@ -606,7 +606,7 @@ void prime_field_tests()
 		"B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B"
 		"3C1856A429BF97E7E31C2E5BD66")) ABORT;
 	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
 		"FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5"
 		"C9B8899C47AEBB6FB71E91386409")) ABORT;
@@ -651,7 +651,7 @@ void prime_field_tests()
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
@@ -764,7 +764,7 @@ void prime_field_tests()
 #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
@@ -782,7 +782,7 @@ void prime_field_tests()
 	if (!BN_hex2bn(&x, _x)) ABORT; \
 	if (!BN_hex2bn(&y, _y)) ABORT; \
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \
+        if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \
 	if (!BN_hex2bn(&z, _order)) ABORT; \
 	if (!BN_hex2bn(&cof, _cof)) ABORT; \
 	if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \
@@ -895,7 +895,7 @@ void char2_field_tests()
 	if (!BN_hex2bn(&y, "8")) ABORT;
 	if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT;
 #endif
-	if (!EC_POINT_is_on_curve(group, Q, ctx))
+	if (EC_POINT_is_on_curve(group, Q, ctx) <= 0)
 		{
 /* Change test based on whether binary point compression is enabled or not. */
 #ifdef OPENSSL_EC_BIN_PT_COMP
@@ -1134,7 +1134,7 @@ void char2_field_tests()
 	if (!EC_POINT_copy(Q, P)) ABORT;
 	if (EC_POINT_is_at_infinity(group, Q)) ABORT;
 	if (!EC_POINT_dbl(group, P, P, ctx)) ABORT;
-	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT;
 	if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */
 
 	if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT;
Index: crypto/openssl/crypto/objects/obj_dat.c
===================================================================
--- crypto/openssl/crypto/objects/obj_dat.c	(revision 284286)
+++ crypto/openssl/crypto/objects/obj_dat.c	(working copy)
@@ -377,6 +377,9 @@ int OBJ_obj2nid(const ASN1_OBJECT *a)
 	if (a->nid != 0)
 		return(a->nid);
 
+	if (a->length == 0)
+	    return NID_undef;
+
 	if (added != NULL)
 		{
 		ad.type=ADDED_DATA;
Index: crypto/openssl/crypto/pkcs7/pk7_doit.c
===================================================================
--- crypto/openssl/crypto/pkcs7/pk7_doit.c	(revision 284286)
+++ crypto/openssl/crypto/pkcs7/pk7_doit.c	(working copy)
@@ -410,6 +410,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, B
 	        goto err;
 		}
 
+    /* Detached content must be supplied via in_bio instead. */
+    if (data_body == NULL && in_bio == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+        goto err;
+    }
+
 	/* We will be checking the signature */
 	if (md_sk != NULL)
 		{
@@ -587,12 +593,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, B
 		}
 
 #if 1
-	if (PKCS7_is_detached(p7) || (in_bio != NULL))
-		{
-		bio=in_bio;
-		}
-	else 
-		{
+	if (in_bio != NULL) {
+		bio = in_bio;
+	} else {
 #if 0
 		bio=BIO_new(BIO_s_mem());
 		/* We need to set this so that when we have read all
Index: crypto/openssl/crypto/x509/x509_vfy.c
===================================================================
--- crypto/openssl/crypto/x509/x509_vfy.c	(revision 284286)
+++ crypto/openssl/crypto/x509/x509_vfy.c	(working copy)
@@ -1040,82 +1040,120 @@ int X509_cmp_current_time(ASN1_TIME *ctm)
 }
 
 int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time)
-	{
+{
 	char *str;
 	ASN1_TIME atm;
 	long offset;
-	char buff1[24],buff2[24],*p;
-	int i,j;
+    char buff1[24], buff2[24], *p;
+    int i, j, remaining;
 
-	p=buff1;
-	i=ctm->length;
-	str=(char *)ctm->data;
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		if ((i < 11) || (i > 17)) return 0;
-		memcpy(p,str,10);
-		p+=10;
-		str+=10;
+    p = buff1;
+    remaining = ctm->length;
+    str = (char *)ctm->data;
+    /*
+     * Note that the following (historical) code allows much more slack in the
+     * time format than RFC5280. In RFC5280, the representation is fixed:
+     * UTCTime: YYMMDDHHMMSSZ
+     * GeneralizedTime: YYYYMMDDHHMMSSZ
+     */
+    if (ctm->type == V_ASN1_UTCTIME) {
+        /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+        int min_length = sizeof("YYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 10);
+        p += 10;
+        str += 10;
+        remaining -= 10;
+    } else {
+        /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
+        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        memcpy(p, str, 12);
+        p += 12;
+        str += 12;
+        remaining -= 12;
 		}
-	else
-		{
-		if (i < 13) return 0;
-		memcpy(p,str,12);
-		p+=12;
-		str+=12;
-		}
 
-	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
-		{ *(p++)='0'; *(p++)='0'; }
-	else
-		{ 
-		*(p++)= *(str++);
-		*(p++)= *(str++);
-		/* Skip any fractional seconds... */
-		if (*str == '.')
-			{
+    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+        *(p++) = '0';
+        *(p++) = '0';
+    } else {
+        /* SS (seconds) */
+        if (remaining < 2)
+            return 0;
+        *(p++) = *(str++);
+        *(p++) = *(str++);
+        remaining -= 2;
+        /*
+         * Skip any (up to three) fractional seconds...
+         * TODO(emilia): in RFC5280, fractional seconds are forbidden.
+         * Can we just kill them altogether?
+         */
+        if (remaining && *str == '.') {
 			str++;
-			while ((*str >= '0') && (*str <= '9')) str++;
+            remaining--;
+            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+                if (*str < '0' || *str > '9')
+                    break;
 			}
-		
 		}
-	*(p++)='Z';
-	*(p++)='\0';
 
-	if (*str == 'Z')
-		offset=0;
-	else
-		{
+    }
+    *(p++) = 'Z';
+    *(p++) = '\0';
+
+    /* We now need either a terminating 'Z' or an offset. */
+    if (!remaining)
+        return 0;
+    if (*str == 'Z') {
+        if (remaining != 1)
+            return 0;
+        offset = 0;
+    } else {
+        /* (+-)HHMM */
 		if ((*str != '+') && (*str != '-'))
 			return 0;
-		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
-		offset+=(str[3]-'0')*10+(str[4]-'0');
+        /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
+        if (remaining != 5)
+            return 0;
+        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+            return 0;
+        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+        offset += (str[3] - '0') * 10 + (str[4] - '0');
 		if (*str == '-')
-			offset= -offset;
+            offset = -offset;
 		}
-	atm.type=ctm->type;
-	atm.length=sizeof(buff2);
-	atm.data=(unsigned char *)buff2;
+    atm.type = ctm->type;
+    atm.length = sizeof(buff2);
+    atm.data = (unsigned char *)buff2;
 
-	if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
 		return 0;
 
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		i=(buff1[0]-'0')*10+(buff1[1]-'0');
-		if (i < 50) i+=100; /* cf. RFC 2459 */
-		j=(buff2[0]-'0')*10+(buff2[1]-'0');
-		if (j < 50) j+=100;
+    if (ctm->type == V_ASN1_UTCTIME) {
+        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+        if (i < 50)
+            i += 100;           /* cf. RFC 2459 */
+        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+        if (j < 50)
+            j += 100;
 
-		if (i < j) return -1;
-		if (i > j) return 1;
+        if (i < j)
+            return -1;
+        if (i > j)
+            return 1;
 		}
-	i=strcmp(buff1,buff2);
+    i = strcmp(buff1, buff2);
 	if (i == 0) /* wait a second then return younger :-) */
 		return -1;
 	else
 		return i;
-	}
+}
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
Index: crypto/openssl/ssl/d1_lib.c
===================================================================
--- crypto/openssl/ssl/d1_lib.c	(revision 284286)
+++ crypto/openssl/ssl/d1_lib.c	(working copy)
@@ -507,6 +507,9 @@ int dtls1_listen(SSL *s, struct sockaddr *client)
 	{
 	int ret;
 
+	/* Ensure there is no state left over from a previous invocation */
+	SSL_clear(s);
+
 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
 	s->d1->listen = 1;
 
Index: crypto/openssl/ssl/s3_clnt.c
===================================================================
--- crypto/openssl/ssl/s3_clnt.c	(revision 284286)
+++ crypto/openssl/ssl/s3_clnt.c	(working copy)
@@ -1805,6 +1805,38 @@ int ssl3_get_new_session_ticket(SSL *s)
 		}
 
 	p=d=(unsigned char *)s->init_msg;
+
+    if (s->session->session_id_length > 0) {
+        int i = s->session_ctx->session_cache_mode;
+        SSL_SESSION *new_sess;
+        /*
+         * We reused an existing session, so we need to replace it with a new
+         * one
+         */
+        if (i & SSL_SESS_CACHE_CLIENT) {
+            /*
+             * Remove the old session from the cache
+             */
+            if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) {
+                if (s->session_ctx->remove_session_cb != NULL)
+                    s->session_ctx->remove_session_cb(s->session_ctx,
+                                                      s->session);
+            } else {
+                /* We carry on if this fails */
+                SSL_CTX_remove_session(s->session_ctx, s->session);
+            }
+        }
+
+        if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
+            al = SSL_AD_INTERNAL_ERROR;
+            SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+            goto f_err;
+        }
+
+        SSL_SESSION_free(s->session);
+        s->session = new_sess;
+    }
+
 	n2l(p, s->session->tlsext_tick_lifetime_hint);
 	n2s(p, ticklen);
 	/* ticket_lifetime_hint + ticket_length + ticket */
Index: crypto/openssl/ssl/s3_srvr.c
===================================================================
--- crypto/openssl/ssl/s3_srvr.c	(revision 284286)
+++ crypto/openssl/ssl/s3_srvr.c	(working copy)
@@ -2012,6 +2012,7 @@ int ssl3_get_client_key_exchange(SSL *s)
 		int                     padl, outl;
 		krb5_timestamp		authtime = 0;
 		krb5_ticket_times	ttimes;
+        int kerr = 0;
 
 		EVP_CIPHER_CTX_init(&ciph_ctx);
 
@@ -2124,19 +2125,22 @@ int ssl3_get_client_key_exchange(SSL *s)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DECRYPTION_FAILED);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		outl += padl;
 		if (outl > SSL_MAX_MASTER_KEY_LENGTH)
@@ -2143,7 +2147,8 @@ int ssl3_get_client_key_exchange(SSL *s)
 			{
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 				SSL_R_DATA_LENGTH_TOO_LONG);
-			goto err;
+            kerr = 1;
+            goto kclean;
 			}
 		if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff))))
 		    {
@@ -2159,7 +2164,8 @@ int ssl3_get_client_key_exchange(SSL *s)
 		        {
 			SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
 			       SSL_AD_DECODE_ERROR);
-			goto err;
+                kerr = 1;
+                goto kclean;
 			}
 		    }
 
@@ -2185,8 +2191,12 @@ int ssl3_get_client_key_exchange(SSL *s)
                 **  kssl_ctx = kssl_ctx_free(kssl_ctx);
                 **  if (s->kssl_ctx)  s->kssl_ctx = NULL;
                 */
-                }
-	else
+
+ kclean:
+        OPENSSL_cleanse(pms, sizeof(pms));
+        if (kerr)
+            goto err;
+    } else
 #endif	/* OPENSSL_NO_KRB5 */
 
 #ifndef OPENSSL_NO_ECDH
Index: crypto/openssl/ssl/ssl.h
===================================================================
--- crypto/openssl/ssl/ssl.h	(revision 284286)
+++ crypto/openssl/ssl/ssl.h	(working copy)
@@ -1851,6 +1851,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_READ					 223
 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT			 187
 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT			 188
+#define SSL_F_SSL_SESSION_DUP				 348
 #define SSL_F_SSL_SESSION_NEW				 189
 #define SSL_F_SSL_SESSION_PRINT_FP			 190
 #define SSL_F_SSL_SESS_CERT_NEW				 225
Index: crypto/openssl/ssl/ssl_err.c
===================================================================
--- crypto/openssl/ssl/ssl_err.c	(revision 284286)
+++ crypto/openssl/ssl/ssl_err.c	(working copy)
@@ -233,6 +233,7 @@ static ERR_STRING_DATA SSL_str_functs[]=
 {ERR_FUNC(SSL_F_SSL_READ),	"SSL_read"},
 {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT),	"SSL_RSA_PRIVATE_DECRYPT"},
 {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT),	"SSL_RSA_PUBLIC_ENCRYPT"},
+{ERR_FUNC(SSL_F_SSL_SESSION_DUP),		"ssl_session_dup"},
 {ERR_FUNC(SSL_F_SSL_SESSION_NEW),	"SSL_SESSION_new"},
 {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP),	"SSL_SESSION_print_fp"},
 {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW),	"SSL_SESS_CERT_NEW"},
Index: crypto/openssl/ssl/ssl_locl.h
===================================================================
--- crypto/openssl/ssl/ssl_locl.h	(revision 284286)
+++ crypto/openssl/ssl/ssl_locl.h	(working copy)
@@ -731,6 +731,7 @@ void ssl_sess_cert_free(SESS_CERT *sc);
 int ssl_set_peer_cert_type(SESS_CERT *c, int type);
 int ssl_get_new_session(SSL *s, int session);
 int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b);
 int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap,
 			const SSL_CIPHER * const *bp);
Index: crypto/openssl/ssl/ssl_sess.c
===================================================================
--- crypto/openssl/ssl/ssl_sess.c	(revision 284286)
+++ crypto/openssl/ssl/ssl_sess.c	(working copy)
@@ -132,6 +132,79 @@ SSL_SESSION *SSL_SESSION_new(void)
 	return(ss);
 	}
 
+/*
+ * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+ * ticket == 0 then no ticket information is duplicated, otherwise it is.
+ */
+SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket)
+{
+    SSL_SESSION *dest;
+
+    dest = OPENSSL_malloc(sizeof(*src));
+    if (dest == NULL) {
+        goto err;
+    }
+    memcpy(dest, src, sizeof(*dest));
+
+    /*
+     * Set the various pointers to NULL so that we can call SSL_SESSION_free in
+     * the case of an error whilst halfway through constructing dest
+     */
+    dest->ciphers = NULL;
+#ifndef OPENSSL_NO_TLSEXT
+    dest->tlsext_hostname = NULL;
+#endif
+    dest->tlsext_tick = NULL;
+    memset(&dest->ex_data, 0, sizeof(dest->ex_data));
+
+    /* We deliberately don't copy the prev and next pointers */
+    dest->prev = NULL;
+    dest->next = NULL;
+
+    dest->references = 1;
+
+    if (src->sess_cert != NULL)
+        CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT);
+
+    if (src->peer != NULL)
+        CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509);
+
+    if(src->ciphers != NULL) {
+        dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers);
+        if (dest->ciphers == NULL)
+            goto err;
+    }
+
+    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION,
+                                            &dest->ex_data, &src->ex_data)) {
+        goto err;
+    }
+
+#ifndef OPENSSL_NO_TLSEXT
+    if (src->tlsext_hostname) {
+        dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname);
+        if (dest->tlsext_hostname == NULL) {
+            goto err;
+        }
+    }
+#endif
+
+    if (ticket != 0) {
+        dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen);
+        if(dest->tlsext_tick == NULL)
+            goto err;
+    } else {
+        dest->tlsext_tick_lifetime_hint = 0;
+        dest->tlsext_ticklen = 0;
+    }
+
+    return dest;
+err:
+    SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE);
+    SSL_SESSION_free(dest);
+    return NULL;
+}
+
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
 	{
 	if(len)
